package day18.inclass;

/**
 * Java四种内部类测试类
 * 
 * Java中有四种内部类：
 * 1. 成员内部类（Member Inner Class）
 * 2. 静态内部类（Static Nested Class）
 * 3. 局部内部类（Local Inner Class）
 * 4. 匿名内部类（Anonymous Inner Class）
 */
public class InnerClassTest {
    // 外部类的属性
    private String outerField = "Outer Field";
    private static String staticOuterField = "Static Outer Field";

    // 将接口定义移到类的顶层作用域
    interface Greeting {
        void sayHello();
    }

    /**
     * 1. 成员内部类（Member Inner Class）
     * 特点：作为外部类的成员存在，可以访问外部类的所有成员（包括private）
     */
    class MemberInnerClass {
        private String innerField = "Member Inner Field";

        // 成员内部类不能定义静态成员（除了编译时常量）
        // private static String staticInnerField = "Static Inner Field"; // 错误

        public void display() {
            System.out.println("成员内部类访问外部类实例变量: " + outerField);
            System.out.println("成员内部类访问自己的实例变量: " + innerField);
        }

        public String getInnerField() {
            return innerField;
        }
    }

    /**
     * 2. 静态内部类（Static Nested Class）
     * 特点：使用static修饰，不依赖于外部类实例，只能直接访问外部类的静态成员
     */
    static class StaticNestedClass {
        private String nestedField = "Static Nested Field";
        private static String staticNestedField = "Static Nested Static Field";

        public void display() {
            // 静态内部类不能直接访问外部类的非静态成员
            // System.out.println(outerField); // 错误
            System.out.println("静态内部类访问外部类静态变量: " + staticOuterField);
            System.out.println("静态内部类访问自己的实例变量: " + nestedField);
            System.out.println("静态内部类访问自己的静态变量: " + staticNestedField);
        }

        public static void staticDisplay() {
            System.out.println("静态内部类静态方法访问外部类静态变量: " + staticOuterField);
        }
    }

    /**
     * 测试成员内部类的方法
     */
    public void testMemberInnerClass() {
        System.out.println("=== 测试成员内部类 ===");
        // 创建成员内部类实例需要先有外部类实例
        MemberInnerClass inner = new MemberInnerClass();
        inner.display();
        System.out.println("获取成员内部类字段: " + inner.getInnerField());
        System.out.println();
    }

    /**
     * 测试静态内部类的方法
     */
    public void testStaticNestedClass() {
        System.out.println("=== 测试静态内部类 ===");
        // 创建静态内部类实例不需要外部类实例
        StaticNestedClass nested = new StaticNestedClass();
        nested.display();
        StaticNestedClass.staticDisplay();
        System.out.println();
    }

    /**
     * 3. 局部内部类（Local Inner Class）
     * 特点：定义在方法内部，作用域仅限于该方法，可以访问方法的final或 effectively final变量
     */
    public void testLocalInnerClass() {
        System.out.println("=== 测试局部内部类 ===");
        final String methodField = "Method Final Field";
        String effectivelyFinalField = "Effectively Final Field";

        // 局部内部类定义在方法内部
        class LocalInnerClass {
            private String localInnerField = "Local Inner Field";

            public void display() {
                System.out.println("局部内部类访问外部类实例变量: " + outerField);
                System.out.println("局部内部类访问外部类静态变量: " + staticOuterField);
                System.out.println("局部内部类访问方法final变量: " + methodField);
                System.out.println("局部内部类访问方法effectively final变量: " + effectivelyFinalField);
                System.out.println("局部内部类访问自己的实例变量: " + localInnerField);
            }
        }

        // 创建并使用局部内部类实例
        LocalInnerClass local = new LocalInnerClass();
        local.display();
        System.out.println();
    }

    /**
     * 4. 匿名内部类（Anonymous Inner Class）
     * 特点：没有名字的内部类，通常用于实现接口或继承类，只能使用一次
     */
    public void testAnonymousInnerClass() {
        System.out.println("=== 测试匿名内部类 ===");

        // 使用匿名内部类实现接口
        Greeting greeting = new Greeting() {
            @Override
            public void sayHello() {
                System.out.println("匿名内部类实现接口方法");
                System.out.println("匿名内部类访问外部类实例变量: " + outerField);
                System.out.println("匿名内部类访问外部类静态变量: " + staticOuterField);
            }
        };

        greeting.sayHello();

        // 另一个匿名内部类的例子 - 继承类
        Thread thread = new Thread() {
            @Override
            public void run() {
                System.out.println("匿名内部类继承Thread类");
                System.out.println("匿名内部类访问外部类实例变量: " + outerField);
            }
        };
        thread.start();

        try {
            thread.join(); // 等待线程执行完毕
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        System.out.println();
    }

    /**
     * 主方法，测试所有四种内部类
     */
    public static void main(String[] args) {
        InnerClassTest test = new InnerClassTest();
        
        // 测试成员内部类
        test.testMemberInnerClass();
        
        // 测试静态内部类
        test.testStaticNestedClass();
        
        // 测试局部内部类
        test.testLocalInnerClass();
        
        // 测试匿名内部类
        test.testAnonymousInnerClass();
        
        System.out.println("所有四种内部类测试完成！");
    }
}